home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / username.c.z / username.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  10.2 KB  |  416 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Username handling
  5.    Copyright (C) Andrew Tridgell 1992-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include "includes.h"
  23. extern int DEBUGLEVEL;
  24.  
  25. /* internal functions - modified versions of the ones in password.c */
  26. static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (char *), int N);
  27. static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (char *), int N);
  28.  
  29. /****************************************************************************
  30. get a users home directory. tries as-is then lower case
  31. ****************************************************************************/
  32. char *get_home_dir(char *user)
  33. {
  34.   static struct passwd *pass;
  35.  
  36.   pass = Get_Pwnam(user,False);
  37.  
  38.   if (!pass) return(NULL);
  39.   return(pass->pw_dir);      
  40. }
  41.  
  42.  
  43. /*******************************************************************
  44. map a username from a dos name to a unix name by looking in the username
  45. map
  46. ********************************************************************/
  47. BOOL map_username(char *user)
  48. {
  49.   static BOOL initialised=False;
  50.   static fstring last_from,last_to;
  51.   FILE *f;
  52.   char *s;
  53.   pstring buf;
  54.   char *mapfile = lp_username_map();
  55.   BOOL mapped_user = False;
  56.  
  57.   if (!*mapfile)
  58.     return False;
  59.  
  60.   if (!*user)
  61.     return False;
  62.  
  63.   if (!initialised) {
  64.     *last_from = *last_to = 0;
  65.     initialised = True;
  66.   }
  67.  
  68.   if (strequal(user,last_to))
  69.     return False;
  70.  
  71.   if (strequal(user,last_from)) {
  72.     DEBUG(3,("Mapped user %s to %s\n",user,last_to));
  73.     fstrcpy(user,last_to);
  74.     return True;
  75.   }
  76.   
  77.   f = fopen(mapfile,"r");
  78.   if (!f) {
  79.     DEBUG(0,("can't open username map %s\n",mapfile));
  80.     return False;
  81.   }
  82.  
  83.   DEBUG(4,("Scanning username map %s\n",mapfile));
  84.  
  85.   while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
  86.     char *unixname = s;
  87.     char *dosname = strchr(unixname,'=');
  88.     BOOL return_if_mapped = False;
  89.  
  90.     if (!dosname)
  91.       continue;
  92.     *dosname++ = 0;
  93.  
  94.     while (isspace(*unixname)) unixname++;
  95.     if ('!' == *unixname) {
  96.       return_if_mapped = True;
  97.       unixname++;
  98.       while (*unixname && isspace(*unixname))
  99.         unixname++;
  100.     }
  101.     
  102.     if (!*unixname || strchr("#;",*unixname)) continue;
  103.  
  104.     {
  105.       int l = strlen(unixname);
  106.       while (l && isspace(unixname[l-1])) {
  107.         unixname[l-1] = 0;
  108.         l--;
  109.       }
  110.     }
  111.  
  112.     if (strchr(dosname,'*') || user_in_list(user,dosname)) {
  113.       DEBUG(3,("Mapped user %s to %s\n",user,unixname));
  114.       mapped_user = True;
  115.       fstrcpy(last_from,user);
  116.       sscanf(unixname,"%s",user);
  117.       fstrcpy(last_to,user);
  118.       if(return_if_mapped) { 
  119.         fclose(f);
  120.         return True;
  121.       }
  122.     }
  123.   }
  124.  
  125.   fclose(f);
  126.  
  127.   /*
  128.    * Setup the last_from and last_to as an optimization so
  129.    * that we don't scan the file again for the same user.
  130.    */
  131.   fstrcpy(last_from,user);
  132.   fstrcpy(last_to,user);
  133.  
  134.   return mapped_user;
  135. }
  136.  
  137. /****************************************************************************
  138. internals of Get_Pwnam wrapper
  139. ****************************************************************************/
  140. static struct passwd *_Get_Pwnam(char *s)
  141. {
  142.   struct passwd *ret;
  143.  
  144.   ret = getpwnam(s);
  145.   if (ret)
  146.     {
  147. #ifdef GETPWANAM
  148.       struct passwd_adjunct *pwret;
  149.       pwret = getpwanam(s);
  150.       if (pwret)
  151.     {
  152.       free(ret->pw_passwd);
  153.       ret->pw_passwd = pwret->pwa_passwd;
  154.     }
  155. #endif
  156.  
  157.     }
  158.  
  159.   return(ret);
  160. }
  161.  
  162.  
  163. /****************************************************************************
  164. a wrapper for getpwnam() that tries with all lower and all upper case 
  165. if the initial name fails. Also tried with first letter capitalised
  166. Note that this changes user!
  167. ****************************************************************************/
  168. struct passwd *Get_Pwnam(char *user,BOOL allow_change)
  169. {
  170.   fstring user2;
  171.   int last_char;
  172.   int usernamelevel = lp_usernamelevel();
  173.  
  174.   struct passwd *ret;  
  175.  
  176.   if (!user || !(*user))
  177.     return(NULL);
  178.  
  179.   StrnCpy(user2,user,sizeof(user2)-1);
  180.  
  181.   if (!allow_change) {
  182.     user = &user2[0];
  183.   }
  184.  
  185.   ret = _Get_Pwnam(user);
  186.   if (ret) return(ret);
  187.  
  188.   strlower(user);
  189.   ret = _Get_Pwnam(user);
  190.   if (ret)  return(ret);
  191.  
  192.   strupper(user);
  193.   ret = _Get_Pwnam(user);
  194.   if (ret) return(ret);
  195.  
  196.   /* try with first letter capitalised */
  197.   if (strlen(user) > 1)
  198.     strlower(user+1);  
  199.   ret = _Get_Pwnam(user);
  200.   if (ret) return(ret);
  201.  
  202.   /* try with last letter capitalised */
  203.   strlower(user);
  204.   last_char = strlen(user)-1;
  205.   user[last_char] = toupper(user[last_char]);
  206.   DEBUG(3, ("Trying username %s\n", user));
  207.   ret = _Get_Pwnam(user);
  208.   if (ret) return(ret);
  209.  
  210.   /* try all combinations up to usernamelevel */
  211.   strlower(user);
  212.   ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel);
  213.   if (ret) return(ret);
  214.  
  215.   if (allow_change)
  216.     fstrcpy(user,user2);
  217.  
  218.   return(NULL);
  219. }
  220.  
  221. /****************************************************************************
  222. check if a user is in a netgroup user list
  223. ****************************************************************************/
  224. static BOOL user_in_netgroup_list(char *user,char *ngname)
  225. {
  226. #ifdef NETGROUP
  227.   static char *mydomain = NULL;
  228.   if (mydomain == NULL)
  229.     yp_get_default_domain(&mydomain);
  230.  
  231.   if(mydomain == NULL)
  232.   {
  233.     DEBUG(5,("Unable to get default yp domain\n"));
  234.   }
  235.   else
  236.   {
  237.     DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
  238.           user, mydomain, ngname));
  239.     DEBUG(5,("innetgr is %s\n",
  240.           innetgr(ngname, NULL, user, mydomain)
  241.           ? "TRUE" : "FALSE"));
  242.  
  243.     if (innetgr(ngname, NULL, user, mydomain))
  244.       return (True);
  245.   }
  246. #endif /* NETGROUP */
  247.   return False;
  248. }
  249.  
  250. /****************************************************************************
  251. check if a user is in a UNIX user list
  252. ****************************************************************************/
  253. static BOOL user_in_group_list(char *user,char *gname)
  254. {
  255. #if HAVE_GETGRNAM 
  256.   struct group *gptr;
  257.   char **member;  
  258.   struct passwd *pass = Get_Pwnam(user,False);
  259.  
  260.   if (pass)
  261.   { 
  262.     gptr = getgrgid(pass->pw_gid);
  263.     if (gptr && strequal(gptr->gr_name,gname))
  264.       return(True); 
  265.   } 
  266.  
  267.   gptr = (struct group *)getgrnam(gname);
  268.  
  269.   if (gptr)
  270.   {
  271.     member = gptr->gr_mem;
  272.     while (member && *member)
  273.     {
  274.       if (strequal(*member,user))
  275.         return(True);
  276.       member++;
  277.     }
  278.   }
  279. #endif /* HAVE_GETGRNAM */
  280.   return False;
  281. }          
  282.  
  283. /****************************************************************************
  284. check if a user is in a user list - can check combinations of UNIX
  285. and netgroup lists.
  286. ****************************************************************************/
  287. BOOL user_in_list(char *user,char *list)
  288. {
  289.   pstring tok;
  290.   char *p=list;
  291.  
  292.   while (next_token(&p,tok,LIST_SEP))
  293.   {
  294.     /*
  295.      * Check raw username.
  296.      */
  297.     if (strequal(user,tok))
  298.       return(True);
  299.  
  300.     /*
  301.      * Now check to see if any combination
  302.      * of UNIX and netgroups has been specified.
  303.      */
  304.  
  305.     if(*tok == '@')
  306.     {
  307.       /*
  308.        * Old behaviour. Check netgroup list
  309.        * followed by UNIX list.
  310.        */
  311.       if(user_in_netgroup_list(user,&tok[1]))
  312.         return True;
  313.       if(user_in_group_list(user,&tok[1]))
  314.         return True;
  315.     }
  316.     else if (*tok == '+')
  317.     {
  318.       if(tok[1] == '&')
  319.       {
  320.         /*
  321.          * Search UNIX list followed by netgroup.
  322.          */
  323.         if(user_in_group_list(user,&tok[2]))
  324.           return True;
  325.         if(user_in_netgroup_list(user,&tok[2]))
  326.           return True;
  327.       }
  328.       else
  329.       {
  330.         /*
  331.          * Just search UNIX list.
  332.          */
  333.         if(user_in_group_list(user,&tok[1]))
  334.           return True;
  335.       }
  336.     }
  337.     else if (*tok == '&')
  338.     {
  339.       if(tok[1] == '&')
  340.       {
  341.         /*
  342.          * Search netgroup list followed by UNIX list.
  343.          */
  344.         if(user_in_netgroup_list(user,&tok[2]))
  345.           return True;
  346.         if(user_in_group_list(user,&tok[2]))
  347.           return True;
  348.       }
  349.       else
  350.       {
  351.         /*
  352.          * Just search netgroup list.
  353.          */
  354.         if(user_in_netgroup_list(user,&tok[1]))
  355.           return True;
  356.       }
  357.     }
  358.   }
  359.   return(False);
  360. }
  361.  
  362. /* The functions below have been taken from password.c and slightly modified */
  363. /****************************************************************************
  364. apply a function to upper/lower case combinations
  365. of a string and return true if one of them returns true.
  366. try all combinations with N uppercase letters.
  367. offset is the first char to try and change (start with 0)
  368. it assumes the string starts lowercased
  369. ****************************************************************************/
  370. static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(char *),int N)
  371. {
  372.   int len = strlen(s);
  373.   int i;
  374.   struct passwd *ret;
  375.  
  376. #ifdef PASSWORD_LENGTH
  377.   len = MIN(len,PASSWORD_LENGTH);
  378. #endif
  379.  
  380.   if (N <= 0 || offset >= len)
  381.     return(fn(s));
  382.  
  383.  
  384.   for (i=offset;i<(len-(N-1));i++)
  385.  
  386.     {
  387.       char c = s[i];
  388.       if (!islower(c)) continue;
  389.       s[i] = toupper(c);
  390.       ret = uname_string_combinations2(s,i+1,fn,N-1);
  391.       if(ret) return(ret);
  392.       s[i] = c;
  393.     }
  394.   return(NULL);
  395. }
  396.  
  397. /****************************************************************************
  398. apply a function to upper/lower case combinations
  399. of a string and return true if one of them returns true.
  400. try all combinations with up to N uppercase letters.
  401. offset is the first char to try and change (start with 0)
  402. it assumes the string starts lowercased
  403. ****************************************************************************/
  404. static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(char *),int N)
  405. {
  406.   int n;
  407.   struct passwd *ret;
  408.  
  409.   for (n=1;n<=N;n++)
  410.   {
  411.     ret = uname_string_combinations2(s,0,fn,n);
  412.     if(ret) return(ret);
  413.   }
  414.   return(NULL);
  415. }
  416.